package com.cskaoyan.javase.array._7call;

import java.util.Arrays;

/**
 * 什么是方法的传值问题？
 * 调用方法时，我们需要传递实参给方法，在方法内部有可能会改变这些实参的值。
 * 那么方法执行完毕后，这些实参的值在原先的方法中会怎么变呢？
 * 这就是方法的传值问题。
 *
 * 关于方法的传值,存在以下两种方法的传值方式
 * 它们是用于解释方法传参的两个情况：
 *      1.值传递（call by value），指的是调用方法时，传入的是实参的拷贝而不是实参本身。
 *      如果Java是值传递的，那么方法改变的是实参拷贝的值，原本实参的值是不会被改变的。
 *      2.引用传递（call by reference），指的是调用方法时，传入的是实参变量的地址，也就是实参本身。
 *      如果Java是引用传递的，方法改变的是实参本身的值，方法结束后，原本实参变量的值会随之改变。
 *
 * Java到底是值传递还是引用传递,下面写代码测试:
 *      1.通过一个将int数值实参变为原先2倍但没有成功的方法调用
 *          说明:
 *          至少对于Java基本数据类型,Java是值传递的
 *          方法得到的是实参的拷贝,无法修改原本实参的取值
 *      2.通过一个将int类型数组的元素变为原先2倍但成功的方法调用
 *          说明:
 *          至少对于Java引用数据类型,Java是引用传递的
 *
 * 以上是很典型的错误结论,是没有仔细分析得出的有偏差的结论
 * 实际上,Java当中只有值传递,Java没有任何引用传递
 * Java的方法始终得到的都是实参的拷贝,不可能得到实参本身(地址)
 *
 * Java值传递可以得出的结论:
 *      1.基本数据类型实参传入方法,传入的是拷贝,方法内部如何修改这个实参,对原先的实参都没有影响
 *          因为修改的是拷贝
 *      2.引用数据类型实参传入方法,传入的是引用的拷贝,这时引用的拷贝和原先的引用指向同一个对象
 *          这时拷贝引用仍然能够操作原先的对象
 *          待到方法结束,引用的拷贝销毁,但对对象的修改已经生效了
 *          我们把这种现象称之为"方法可以改变对象的状态"
 *          对象的状态: 对象中属性(元素)的取值
 *      3.Java的值传递,只能将实参的拷贝传入方法,不可能传入方法实参本身
 *          比如基本数据类型实参,传入方法的就是这个变量的拷贝
 *          比如引用数据类型实参,传入方法的就是引用的拷贝
 *
 * 总结：Java方法对方法参数能做什么？
 *      1.任何Java方法，都不可能修改另外一个方法中的局部变量，包括:
 *          其它方法中的基本数据类型变量
 *          其它方法中的引用数据类型的引用
 *      可以想象，如果上述修改能够成立，就违背了局部变量的设计原则。
 *
 *   2.（重点）Java方法可以修改对象的状态
 *          因为方法得到的是引用的拷贝，拷贝引用仍然指向原先引用指向的对象。
 *
 * @since 15:59
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        int num = 10;
        doubleIntVale(num);
        // num的取值在main方法中,会变成它的2倍吗?
        System.out.println(num);

        System.out.println("--------------------");

        int[] arr = {1, 2, 3};
        doubleEleIntArr(arr);
        System.out.println(Arrays.toString(arr));

        System.out.println("----------------------");

        int[] arr1 = {9, 9, 9};
        int[] arr2 = {6, 6, 6};
        /*
            如果交换成功了,说明是引用传递,因为引用传递得到的就是引用本身,它应该是交换成功的
            如果交换失败了,说明是值传递,因为传入的是引用的拷贝,方法内部交换拷贝成功,不影响实参引用.
         */
        System.out.println("交换之前的arr1:" + Arrays.toString(arr1));
        System.out.println("交换之前的arr2:" + Arrays.toString(arr2));
        swapIntArrReference(arr1, arr2);
        System.out.println("交换之后的arr1:" + Arrays.toString(arr1));
        System.out.println("交换之后的arr2:" + Arrays.toString(arr2));
    }

    public static void doubleIntVale(int num) {
        num *= 2;
        System.out.println("double方法内部:" + num);
    }

    public static void doubleEleIntArr(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] *= 2;
        }
    }

    public static void swapIntArrReference(int[] arr1, int[] arr2) {
        int[] temp = arr1;
        arr1 = arr2;
        arr2 = temp;
        System.out.println("交换的方法中的arr1:" + Arrays.toString(arr1));
        System.out.println("交换的方法中的arr2:" + Arrays.toString(arr2));
    }
}
